package com.start.platform.wx;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.start.common.exceptions.StartBusException;
import com.start.common.tools.SpringContextTools;
import com.start.platform.core.StartBasePlatformService;
import com.start.platform.core.entity.StartPlatformConfigEntity;
import com.start.platform.core.entity.StartPlatformFans;
import com.start.platform.core.service.StartPlatformFansService;
import com.start.platform.core.vo.StartPlatformFansDetail;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class WeiXinMpPlatformService implements StartBasePlatformService<WxMpService> {

    private static final Map<String, WxMpService> wxMpServiceMap = new HashMap<>();
    private static final Map<String, WxMpMessageRouter> wxMpMessageRouterMap = new HashMap<>();

    @Autowired
    private StartPlatformFansService platformFansService;


    /**
     * 平台类型
     *
     * @return
     */
    @Override
    public String getPlatformType() {
        return SystemConstant.PlatformTypes.WX.MP;
    }

    @Override
    public String getPlatformTypeLabel() {
        return "微信公众号";
    }

    @Override
    public void add(StartPlatformConfigEntity entity) {
        if (wxMpServiceMap.containsKey(entity.getAppId())) {
            return;
        }
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(createWxMpConfigStorage(entity));
        wxMpServiceMap.put(entity.getAppId(), wxMpService);
        wxMpMessageRouterMap.put(entity.getAppId(), new WxMpMessageRouter(wxMpService));
    }


    private WxMpConfigStorage createWxMpConfigStorage(StartPlatformConfigEntity entity) {
        WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
        config.setAppId(entity.getAppId());
        config.setSecret(entity.getSecret());
        config.setAesKey(entity.getAesKey());
        config.setToken(entity.getToken());
        return config;
    }

    @Override
    public void remove(String appId) {
        if (!wxMpServiceMap.containsKey(appId)) {
            return;
        }
        wxMpServiceMap.remove(appId);
        wxMpMessageRouterMap.remove(appId);
    }

    /**
     * 修改配置
     *
     * @param appId
     * @param config
     */
    @Override
    public void updateByAppId(String appId, StartPlatformConfigEntity config) {
        if (wxMpServiceMap.containsKey(appId)) {
            return;
        }
        remove(appId);
        add(config);
    }

    /**
     * 是否存在AppId
     *
     * @param appId
     * @return
     */
    @Override
    public boolean hasAppId(String appId) {
        return wxMpServiceMap.containsKey(appId);
    }


    @Override
    public WxMpService getPlatformService(String appId) {
        if (!wxMpServiceMap.containsKey(appId)) {
            return null;
        }
        return wxMpServiceMap.get(appId);
    }



    @Override
    public StartPlatformFansDetail getUserInfoByPlatformCode(String appId, String code, JSONObject prop) {
        WxMpUser wxMpUser = getUserInfo(appId, code);
        StartPlatformFans fans = platformFansService.getFansByOpenId(SystemConstant.PlatformTypes.WX.MP, appId, wxMpUser.getOpenId());
        StartPlatformFansDetail detail = null;
        if (fans == null) {
            detail = new StartPlatformFansDetail();
            detail.setPlatformOpenId(wxMpUser.getOpenId());
            detail.setPlatformAppId(appId);
            detail.setPlatformType(SystemConstant.PlatformTypes.WX.MP);
            detail.setNewUser(true);
        } else {
            detail = StartPlatformFansDetail.create(fans);
        }
        detail.setPlatformFansInfo((JSONObject) JSONObject.from(wxMpUser));
        detail.setNickName(wxMpUser.getNickname());
        detail.setAvatar(getUserHeadImg(wxMpUser));
        detail.setSex(wxMpUser.getSex());
        detail.setPlatformLastLoginTime(LocalDateTime.now());
        platformFansService.saveOrUpdate(detail);
        return detail;

    }

    private JSONArray getUserHeadImg(WxMpUser wxMpUser) {
        String headImgUrl = wxMpUser.getHeadImgUrl();
        if (StringUtils.isAllBlank(headImgUrl)) {
            return new JSONArray();
        }
        JSONObject avatar = new JSONObject();
        avatar.put("label", "");
        avatar.put("value", headImgUrl);
        JSONArray array = new JSONArray();
        array.add(avatar);
        return array;
    }

    private WxMpUser getUserInfo(String appId, String code) {
        WxMpService wxMpService = getPlatformService(appId);
        WxMpUser wxMpUser;
        try {
            WxOAuth2AccessToken oAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
            String openId = oAuth2AccessToken.getOpenId();
            return wxMpService.getUserService().userInfo(openId);
        } catch (WxErrorException e) {
            e.printStackTrace();
            throw new StartBusException("微信登录失败请重新登录");
        }
    }

    public WxMpMessageRouter getWxMpMessageRouter(String appId) {
        return wxMpMessageRouterMap.get(appId);
    }

    public WxMpXmlOutMessage route(String appId, WxMpXmlMessage message) {
        return getWxMpMessageRouter(appId).route(message);
    }

    /**
     * 平台验证token
     *
     * @param appId
     * @return
     */
    @Override
    public Object platformVerifyToken(String appId) {

        String signature = SpringContextTools.getHttpServletRequest().getParameter("signature");
        String timestamp = SpringContextTools.getHttpServletRequest().getParameter("timestamp");
        String nonce = SpringContextTools.getHttpServletRequest().getParameter("nonce");
        String echostr = SpringContextTools.getHttpServletRequest().getParameter("echostr");
        log.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);
        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        if (!hasAppId(appId)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appId));
        }
        WxMpService platformService = getPlatformService(appId);
        if (platformService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }
        return "非法请求";
    }
//    /**
//     * 迁移用户信息
//     *
//     * @param oldConfigEntity
//     * @param newConfigEntity
//     * @return
//     */
//    @Override
//    public PlatformTransferResult transferUserInfo(ThirdPlatformConfigEntity oldConfigEntity, ThirdPlatformConfigEntity newConfigEntity) {
//        if (!oldConfigEntity.getPlatformType().equals(SystemConstant.PlatformTypes.WX.MP)) {
//            throw new StartBusException("不支持的平台类型");
//        }
//        if(oldConfigEntity.getId().equals(newConfigEntity.getId()))return new PlatformTransferResult();
//        LambdaQueryWrapper<ThirdPartyPlatformFansUserEntity> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(ThirdPartyPlatformFansUserEntity::getAppId, oldConfigEntity.getAppId());
//        queryWrapper.eq(ThirdPartyPlatformFansUserEntity::getPlatformType, oldConfigEntity.getPlatformType());
//        Page<ThirdPartyPlatformFansUserEntity> page = new Page<>();
//        page.setCurrent(1);
//        page.setSize(50);
//        final PlatformTransferResult result = new PlatformTransferResult();
//        List<ThirdPartyPlatformFansUserEntity> updateList = new ArrayList<>();
//        do {
//            page = platformFansService.page(page, queryWrapper);
//            result.setTotal(page.getTotal());
//            log.info("开始迁移第" + page.getCurrent() + "组");
//            final WxMpService service = getService(newConfigEntity.getAppId());
//            List<String> openIds = page.getRecords().stream().map(ThirdPartyPlatformFansUserEntity::getOpenId).collect(Collectors.toList());
//            final Map<String, List<ThirdPartyPlatformFansUserEntity>> cacheUserInfo = page.getRecords().stream().collect(Collectors.groupingBy(ThirdPartyPlatformFansUserEntity::getOpenId));
//
//            try {
//                final List<WxMpChangeOpenid> wxMpChangeOpenids = service.getUserService().changeOpenid(oldConfigEntity.getAppId(), openIds);
//                for (WxMpChangeOpenid wxMpChangeOpenid : wxMpChangeOpenids) {
//                    if (StringUtils.isEmpty(wxMpChangeOpenid.getNewOpenid())) continue;
//                    if (!cacheUserInfo.containsKey(wxMpChangeOpenid.getOriOpenid())) continue;
//                    final List<ThirdPartyPlatformFansUserEntity> thirdPartyPlatformFansUserEntities = cacheUserInfo.get(wxMpChangeOpenid.getOriOpenid());
//                    if (thirdPartyPlatformFansUserEntities.size() < 1) continue;
//                    final ThirdPartyPlatformFansUserEntity thirdPartyPlatformFansUserEntity = thirdPartyPlatformFansUserEntities.get(0);
//                    thirdPartyPlatformFansUserEntity.setOpenId(wxMpChangeOpenid.getNewOpenid());
//                    thirdPartyPlatformFansUserEntity.setAppId(newConfigEntity.getAppId());
//                    updateList.add(thirdPartyPlatformFansUserEntity);
//                }
//            } catch (WxErrorException e) {
//                e.printStackTrace();
//            }
//            log.info("迁移第" + page.getCurrent() + "完成");
//            page.setCurrent(page.getCurrent() + 1);
//        } while (page.hasNext());
//        if (updateList.size() < 1) return result;
//        platformFansService.updateBatchById(updateList);
//        result.setSuccessNum(updateList.size());
//        return result;
//    }
}
